package com.wkbb.common.utils;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

/**
 * 线程池
 */
@Slf4j
public class ThreadPoolUtil {

    /**
     * 添加消息处理的任务
     * @param r
     */
    public static void addTask(Runnable r) {
        executor.submit(r);
    }


    /**
     * 线程池默认阻塞队列默认值 （分两步：1第一次满的时候开启最大线程数 2第二次满的时候启用拒绝策略 默认为200）
     */
    private final static int MAX_BLOCKING_QUEUE_SIZE = 2000;

    /**
     * 最大线程活跃时间(单位：秒)
     */
    private final static Long KEEP_ALIVE_TIME = 600L;

    /**
     * 线程池初始化大小，默认为cpu核数
     */
    private volatile static int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors()*10;

    /**
     * 依据处理器数个数x2初始化线程池的大小
     */
    private static ExecutorService executor = Executors.newScheduledThreadPool(CORE_POOL_SIZE<8 ? CORE_POOL_SIZE*20: CORE_POOL_SIZE* 10);


    /**
     * 线程池维护线程的最大数量
     * 1、CPU密集型：操作内存处理的业务，一般线程数设置为：CPU核数 + 1 或者 CPU核数*2。核数为4的话，一般设置 5 或 8
     * 2、IO密集型：文件操作，网络操作，数据库操作，一般线程设置为：cpu核数 / (1-0.9)，核数为4的话，一般设置 40
     */
    private final static int MAX_POOL_SIZE = CORE_POOL_SIZE * 8;//放大2倍

    /**
     * 线程池
     */
    private volatile static ExecutorService executorService = null;

    /**
     * 单例模式创建唯一的线程池
     * @return 线程池对象
     */
    public static ExecutorService getExecutorService(){
        if(executorService == null){
            synchronized (ThreadPoolUtil.class){
                if(executorService == null){
                    log.info("线程池初始化....CORE_POOL_SIZE:{},MAX_POOL_SIZE:{},KEEP_ALIVE_TIME:{},MAX_BLOCKING_QUEUE_SIZE:{}",
                            CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, MAX_BLOCKING_QUEUE_SIZE);
                    ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("wkbb-thread-pool-%d").build();
                    executorService = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME,
                            TimeUnit.SECONDS, new LinkedBlockingQueue<>(MAX_BLOCKING_QUEUE_SIZE),
                            namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
                }
            }
        }
        return executorService;
    }

    /**
     * 提交线程池任务
     * @param runnable 线程类
     */
    public static void addPoolTask(Runnable runnable){
        ExecutorService executorService=getExecutorService();
        executorService.submit(runnable);
    }

    /**
     * 提交线程池任务
     * @param callable 异步线程类
     */
    public static <T> Future<T> addPoolTask(Callable<T> callable){
        ExecutorService executorService=getExecutorService();
        return executorService.submit(callable);
    }
}
